package com.nstskj.study.netty.tcp.netty.protocol.executor;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.thread.ExecutorBuilder;
import cn.hutool.core.thread.ThreadUtil;
import com.nstskj.study.netty.tcp.netty.config.properties.NettyNetDevTcpServerProperties;
import com.nstskj.study.netty.tcp.netty.config.properties.ThreadExecutionProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author ZhouChuGang
 * @version 1.0
 * @project nstskj-study-netty-tcp-spring
 * @date 2021/5/4 17:12
 * @Description 抽象的执行器，主要是为了统一配置线程池
 */
@Slf4j
public abstract class AbstractWorkExecutor implements InitializingBean {

    /**
     * 服务端配置
     */
    @Autowired
    private NettyNetDevTcpServerProperties nettyNetDevTcpServerProperties;

    /**
     * 线程池配置参数
     */
    private ThreadExecutionProperties threadExecutionProperties;

    /**
     * 线程工厂
     */
    ThreadFactory threadFactory;

    /**
     * 线程池
     */
    private ThreadPoolExecutor threadPoolExecutor;

    /**
     * 得到对应的线程池配置参数
     *
     * @param nettyNetDevTcpServerProperties
     * @return
     */
    protected abstract ThreadExecutionProperties getThreadExecutionProperties(NettyNetDevTcpServerProperties nettyNetDevTcpServerProperties);

    /**
     * 初始化线程池
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        this.threadExecutionProperties = getThreadExecutionProperties(this.nettyNetDevTcpServerProperties);
        Assert.notNull(threadExecutionProperties);
        //先创建线程工厂
        threadFactory = ThreadUtil.newNamedThreadFactory(threadExecutionProperties.getThreadNamePrefix(), true);
        threadPoolExecutor = ExecutorBuilder.create()
                .setThreadFactory(this.threadFactory)
                //核心线程数
                .setCorePoolSize(threadExecutionProperties.getCoreSize())
                .setMaxPoolSize(threadExecutionProperties.getMaxSize())
                //保持时间
                .setKeepAliveTime(threadExecutionProperties.getKeepAlive().toNanos())
                //是否允许超时堵塞
                .setAllowCoreThreadTimeOut(threadExecutionProperties.isAllowCoreThreadTimeout())
                .build();
    }

    public NettyNetDevTcpServerProperties getNettyNetDevTcpServerProperties() {
        return nettyNetDevTcpServerProperties;
    }

    public ThreadExecutionProperties getThreadExecutionProperties() {
        return threadExecutionProperties;
    }

    public ThreadFactory getThreadFactory() {
        return threadFactory;
    }

    public ThreadPoolExecutor getThreadPoolExecutor() {
        return threadPoolExecutor;
    }
}
